package com.axend.lib_base.livedatabus;

import android.os.Handler;
import android.os.Looper;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenjiasheng
 * @description解决在非viewModel中使用liveData出现内存泄漏的情况
 * @time 2023/8/18 15:51
 */
public class SafeLiveData<T> extends MutableLiveData<T> {

    private static volatile Handler handler;

    private static boolean isInMainThread() {
        return Looper.getMainLooper() == Looper.myLooper();
    }

    private static Handler getHandler() {
        if (handler == null) {
            synchronized (SafeLiveData.class) {
                if (handler == null) {
                    handler = new Handler(Looper.getMainLooper());
                }
            }
        }
        return handler;
    }

    private static void runInMainThread(Runnable runnable) {
        boolean inMainThread = isInMainThread();
        if (inMainThread) {
            runnable.run();
        } else {
            getHandler().post(runnable);
        }
    }

    public static <T> void setValueSync(MutableLiveData<T> liveData, T value) {
        if (liveData == null) {
            return;
        }
        if (isInMainThread()) {
            liveData.setValue(value);
            return;
        }
        Runnable runnable = () -> {
            synchronized (liveData) {
                try {
                    liveData.setValue(value);
                } finally {
                    liveData.notify();
                }
            }
        };
        synchronized (liveData) {
            getHandler().post(runnable);
            try {
                liveData.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private final MutableLiveData<T> realLiveData;

    private final List<WeakReference<Observer<? super T>>> observerReferenceList = new ArrayList();

    public SafeLiveData(MutableLiveData<T> liveData) {
        super();
        realLiveData = liveData;
    }

    public SafeLiveData() {
        super();
        realLiveData = new MutableLiveData<T>();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        runInMainThread(() -> {
            int size = observerReferenceList.size();
            for (int i = 0; i < size; i++) {
                Observer<? super T> observer = observerReferenceList.get(i).get();
                if (observer != null) {
                    realLiveData.removeObserver(observer);
                }
            }
        });
    }


}